/**
* @file drv_cst3xx.c
* @brief  ctp driver
* @details 
* @author huangbin
* @version V1.0.0
* @date 2025-05-10
* @copyright All documents are copyrighted by Shenzhen Xinlongwei Technology Co., LTD.
*            They may not be used for commercial purposes without permission
*/
#include "inc.h"



////////////////////////////////////////////////////
static bool tp_reg_write(uint16_t reg_addr, uint8_t *reg_data, uint8_t cnt)
{
    I2C_ACK_STATUS ack;
	
	I2c_Start();
	I2c_WriteByte(TP_IIC_SLAVE_ADDR);
	I2c_WriteByte(reg_addr >> 8);  //register
	I2c_WriteByte(reg_addr & 0xFF); //nack
    if((reg_data != NULL) && cnt)
    {
        for ( uint16_t i = 0; i < cnt; i++ )
        {
            I2c_WriteByte(reg_data[i]);
        }
    }
	I2c_Stop();
	
	return true;
}
static bool tp_reg_read(uint16_t reg_addr, uint8_t *reg_data, uint8_t cnt)
{
	I2C_ACK_STATUS ack;
	I2C_ACK_STATUS sendAck = I2C_ACK;
	
    tp_reg_write(reg_addr,NULL,0);
	I2c_Start();
	ack = I2c_WriteByte(TP_IIC_SLAVE_ADDR|0x01); //read
	if ( ack != I2C_ACK )
	{
        DebugPrintf("CST3xx read ack error...\r\n"); 
        return false;
	}
	for (uint16_t i = 0; i < cnt; i++ )
	{
		if ( i == cnt-1){
			sendAck = I2C_NAK;
		}
		reg_data[i] = I2c_ReadByte(sendAck);
	}
	I2c_Stop();
	return true;
}
/////////////////////////////////// api ///////////////////////////////////////
Mouse_Typedef MouseData;
/*
chip id:
CST328 : 0x0328
*/
void tp_Cstxx_get_ChipId(void)
{
	uint8_t buf[10];
    uint16_t temp;
    
    tp_reg_write(0xD101,NULL,0); //enter debug mode,read chip info
	tp_reg_read(0xD1F8,buf,4); //x,y resolution ratio
	DebugPrintf("CST3xx 0xD1F8 = 0x%02X,0x%02X,0x%02X,0x%02X\r\n",buf[0],buf[1],buf[2],buf[3]);  //0xF0,0x00,0x40,0x01
	DebugPrintf("CST3xx resolution ratio x= %d,y = %d\r\n",buf[0]+buf[1]*256,buf[2]+buf[3]*256); 

	tp_reg_read(0xD1FC,buf,4); //fw checksum,bootloade time
	DebugPrintf("CST3xx 0xD1FC = 0x%02X,0x%02X,0x%02X,0x%02X\r\n",buf[0],buf[1],buf[2],buf[3]);   
	DebugPrintf("CST3xx checksum = 0x%02X%02X,boottimer = 0x%04X\r\n",buf[2],buf[3],buf[0]+buf[1]*256);   

	tp_reg_read(0xD204,buf,4); //ic type,project id
	DebugPrintf("CST3xx 0xD204 = 0x%02X,0x%02X,0x%02X,0x%02X\r\n",buf[0],buf[1],buf[2],buf[3]);   
    temp = buf[3] << 8 | buf[2];
    temp = (temp / 1000) << 12 | (temp % 1000 / 100) << 8 | (temp % 100 / 10) << 4 | (temp % 10);
	DebugPrintf("CST3xx ic type=0x%04x,project id = 0x%02X%02X\r\n",temp,buf[0],buf[1]);   

	tp_reg_read(0xD208,buf,4); //firware version
	DebugPrintf("CST3xx firware version 0xD208 = 0x%02X,0x%02X,0x%02X,0x%02X\r\n",buf[0],buf[1],buf[2],buf[3]);   
    
	tp_reg_read(0xD20C,buf,4); //firware checksum 
	DebugPrintf("CST3xx firware checksum  0xD20C = 0x%02X,0x%02X,0x%02X,0x%02X\r\n",buf[0],buf[1],buf[2],buf[3]);   //0xF0,0x00,0x40,0x01
    tp_reg_write(0xD109,NULL,0); //enter normal mode
}
#include "gui_core.h"
//mouse_type:动作类型
//index:哪一个手指
static void tpSendMessage(uint8_t mouse_type,uint16_t index,int16_t x,int16_t y)
{
    uint8_t chPointerEvent;
    if(mouse_type == MOUSE_UP)
        chPointerEvent = GUI_MSG_POINTER_EVT_UP;
    else if(mouse_type == MOUSE_MOVE)
        chPointerEvent = GUI_MSG_POINTER_EVT_HOLD;
    else
        chPointerEvent = GUI_MSG_POINTER_EVT_DOWN;
    gui_send_pointer_evt(guiGetInstance(),chPointerEvent,index,x,y);
}
#define TOUCH_X_RES     320 //x方向分辨率
#define TOUCH_Y_RES     240 //y方向分辨率
#define CONFIG_CST328_SWAPXY 
#define CONFIG_CST328_INVERT_X
#define CONFIG_CST328_INVERT_Y
uint32_t tp_Cstxx_get_data(void)
{
    uint16_t x, y,xchip,ychip;
	uint8_t finger_status;
    uint8_t buf[8];
//	tp_Cstxx_get_ChipId();
	tp_reg_read(0xD000,buf,7); 
	finger_status = buf[0] & 0x0F; //0x06=手指按下
	xchip = (buf[1] << 4) | ((buf[3] & 0xF0) >> 4);
	ychip = (buf[2] << 4) | ((buf[3] & 0x0F) >> 0);
    
#ifdef CONFIG_CST328_SWAPXY //交换xy
    uint16_t swap_buf = xchip;
    xchip = ychip;
    ychip = swap_buf;
#endif
#ifdef CONFIG_CST328_INVERT_X //颠倒x
    
    x  = TOUCH_X_RES - xchip;
#endif
#ifdef CONFIG_CST328_INVERT_Y //颠倒y
    y = TOUCH_Y_RES - ychip;
#endif

//    y= TOUCH_Y_RES - xchip; //交换方向
//    x= TOUCH_X_RES - ychip;
//	DebugPrintf("x = %d,y=%d,gesture=0x%02X,finger num = %d\r\n",x,y,ges,finger_num); 
	if(finger_status == 0x06) //按下了
	{
		if(MouseData.Status == MOUSE_DOWN) //上一次也是按下
		{
			if((MouseData.x == x) && (MouseData.y == y)) //坐标没有移动
			{
				return 0;
			}
			//按下并且移动了
			tpSendMessage(MOUSE_MOVE,1,x,y);
//            DebugPrintf("mouse move x= %d,y=%d\r\n",x,y);   
		}
		else //第一次按下
		{
			tpSendMessage(MOUSE_DOWN,1,x,y);
//            DebugPrintf("mouse down x= %d,y=%d\r\n",x,y);   
		}
		MouseData.x = x;	
		MouseData.y = y;
		MouseData.Status = MOUSE_DOWN; //更新状态及坐标
	}
	else //弹起
	{
//        DebugPrintf("mouse up x= %d,y=%d\r\n",x,y);   
        tpSendMessage(MOUSE_UP,1,x,y);
		MouseData.x = INVALID_COOR;	//防止下一次在同一个地方按下
		MouseData.y = INVALID_COOR;
		MouseData.Status = MOUSE_UP; //更新状态及坐标
	}
    return 0;
}
void tp_Cstxx_Init(void)
{
    MouseData.x = INVALID_COOR;
    MouseData.y = INVALID_COOR;
    MouseData.Gesture = 0;
    MouseData.Status = MOUSE_UP;
}

//中断初始化
void tp_IntInit(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef  EXTI_InitStructure;
	
	RCC_APB2PeriphClockCmd(TP_INT_PORT_CLK|RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = TP_INT_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//下降沿触发中断
	GPIO_Init(TP_INT_PORT, &GPIO_InitStructure);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource7);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	EXTI_InitStructure.EXTI_Line=EXTI_Line7;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	EXTI_Init(&EXTI_InitStructure);   
    EXTI_ClearITPendingBit(EXTI_Line7);
}
void EXTI9_5_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line7)==SET)
    {
        tp_Cstxx_get_data();
    }
    EXTI_ClearITPendingBit(EXTI_Line7); //放到if条件里面清除中断，上电后会一直有中断，为什么？
}
void tp_Reset(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd (TP_RESET_PORT_CLK,ENABLE);

	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;

	GPIO_InitStructure.GPIO_Pin = TP_RESET_PIN;
	GPIO_Init (TP_RESET_PORT, & GPIO_InitStructure );

	TP_RESET_HIGH();
	HardWareDelay_ms(10);
	TP_RESET_LOW();
	HardWareDelay_ms(20);
	TP_RESET_HIGH();
	HardWareDelay_ms(100); //>200ms
}

void tp_Init(void)
{
    tp_Cstxx_Init();
    I2c_Init();
    tp_Reset();
//    tp_Cstxx_get_ChipId(); //芯片复位后有一些int发生，要把中断初始化放到读完信息后。
    tp_IntInit();
}


















//////////////////////////////////////////////////////////



